﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Ch.Admin.Bfs.Sms.Sdmx.Extension.CodeBook.Meta
{
    /// <summary>
    /// This hierarchy holds nodules to be used for codebook generation
    /// </summary>
    public class BookHierarchy
    {
        private HierarchyNode bookRoot;

        /// <summary>
        /// Exposes module types and their content as a list of nodes
        /// </summary>
        public Hierarchy Nodes
        {
            get
            {
                return bookRoot.Nodes;
            }
        }

        public HierarchyNode Book { get { return bookRoot; } }

        public string BookFullId { get; set; }

        /// <summary>Construct an empty container </summary>
        public BookHierarchy()
        {
            BookFullId = string.Empty;
            InitHierarchy(false);
        }
        /// <summary> Parametrized Container constructor</summary>
        /// <param name="FullTableContent">True includes all possible module type, false create empty.</param>
        public BookHierarchy(string bookId, bool FullTableContent)
        {
            if (bookId == null)
                bookId = string.Empty;
            BookFullId = bookId;
            InitHierarchy(FullTableContent);
        }

        public BookHierarchy(HierarchyNode root)
        {
            bookRoot = root;
            BookFullId = root.Id;
        }

        /// <summary>
        /// Init an empty Book or a book with all possible modules types
        /// </summary>
        /// <param name="FullTableContent">True init all possible content</param>
        private void InitHierarchy(bool FullTableContent)
        {
            // Create Book Root Node
            bookRoot = new HierarchyNode(TableOfContents.Book.ToString() + " " + BookFullId, null, TableOfContents.Book);

            // Create 1st level nodes
            if (FullTableContent)
                foreach (TableOfContents toc in Enum.GetValues(typeof(TableOfContents)))
                    if (toc != TableOfContents.Book)
                        bookRoot.Nodes.Add(new HierarchyNode(toc.ToString(), null, toc));

        }

        public void AddModule(TableOfContents moduleType, string fullId)
        {
            // Ensure module type exists already
            HierarchyNode moduleNode = GetModuleContainer(moduleType);
            if (moduleNode == null)
                moduleNode = CreateModuleContainer(moduleType);

            // Check if not already selected
            bool alreadySelected = false;
            foreach (HierarchyNode nd in moduleNode.Nodes)
                if (nd.Id == fullId)
                {
                    alreadySelected = true;
                    break;
                }

            if (!alreadySelected)
            {
                // Create child node with fullId
                HierarchyNode childNode = new HierarchyNode(fullId, null, moduleType);
                // Only one overview
                if (moduleType == TableOfContents.Overview && moduleNode.Nodes.Count > 0)
                    moduleNode.Nodes.Clear();

                moduleNode.Nodes.Add(childNode);
            }
        }

        private HierarchyNode GetModuleContainer(TableOfContents moduleType)
        {
            foreach (HierarchyNode node in Book.Nodes)
                if ((int)node.Tag == (int)moduleType)
                    return node;
            return null;
        }

        private HierarchyNode CreateModuleContainer(TableOfContents moduleType)
        {
            //locate position for creation in tree
            int indexNode = 0;
            foreach (HierarchyNode node in Book.Nodes)
            {
                int tocIndex = (int)node.Tag;
                if (tocIndex > (int)moduleType)
                    break;

                ++indexNode;
            }
            // Index 0 if for full book
            HierarchyNode moduleNode = new HierarchyNode(moduleType.ToString(), null, moduleType);
            bookRoot.Nodes.Insert(indexNode, moduleNode);

            return moduleNode;
        }

    }

    /// <summary>
    /// Enumerates types of modules available for Codebook generation
    /// </summary>
    public enum TableOfContents
    {
        Book,
        Overview,
        Catalog,
        DataTables,
        Questionnaires,
        Hierarchies,
        Correspondences,
        Codelists
    }

}
